#include <iostream>
#include <memory>
#include <string>
#include <functional>
#include "TcpServer.hpp"
#include "Protocol.hpp"
#include "Calculate.hpp"

void Usage(const string proc)
{
    cout << "Usage:\n\t" << proc << " local_port" << endl;
}

using task_t = function<Response(const Request &)>;

class CalService
{
public:
    CalService(task_t task)
    :_task(task)
    {

    }

    void Service(socket_sptr sockptr, InetAddr client)
    {
        string clientaddr = "[" + client.IP() + ":" + to_string(client.Port()) + "]# ";
        string message; // 获取消息时不断追加,使用结束时message中的第一条报文自动删除
        while (true)
        {
            // 1.获取客户端消息
            int n = sockptr->Recv(&message);
            if (n < 0)
            {
                LOG(FATAL, "%s quit", clientaddr.c_str());
                break;
            }
            // 2.检测获取的报文是否至少存在一条完整的报文
            // string Decode(std::string& message)
            string package = Decode(message);
            if (package == std::string())
            {
                continue;
            }
            // 3.将Request请求的json串转换为结构化数据
            Request req;
            req.Deserialize(package);

            // 4.业务处理
            Response resp=_task(req);
            // 5.处理结果序列化
            string result;
            resp.Serialize(&result);
            // 6.添加协议报头
            string send_str=Encode(result);
            // 7.发送数据
            sockptr->Send(send_str);
        }
    }

    ~CalService()
    {

    }
private:
    task_t _task;
};

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        Usage(argv[0]);
        exit(USAGE_ERROR);
    }
    EnableScreen();
    uint16_t port = stoi(argv[1]);

    Calculate calculate;
    task_t task=std::bind(&Calculate::Excute,&calculate,std::placeholders::_1);
    
    CalService cal(task);
    io_service_t Service=std::bind(&CalService::Service,cal,std::placeholders::_1,std::placeholders::_2);
    unique_ptr<TcpServer> tsvr(new TcpServer(port, Service));
    tsvr->Loop();
    return 0;
}